package org.praisebase.pbpj.component;

import java.util.ArrayList;
import java.util.UUID;

/**
 *
 * @author Nicolas Perrenoud <nicu@lavine.ch>
 */
public class Song {

	/**
	 * Unique ID which allows the song to be identified even when 
	 * the title changes
	 */
	private UUID uuid;
	
	/**
	 * Title(s) of the song
	 */
	private ArrayList<SongTitle> titles = new ArrayList<SongTitle>();
	
	/**
	 * Author(s) of the song
	 */
	private ArrayList<SongAuthor> authors = new ArrayList<SongAuthor>();
	
	/**
	 * Copyright information
	 * 
	 * In some countries it is a legal requirement to display copyright 
	 * information during the presentation of songs. The variable
	 * has no specific format, though it is recommended that the value 
	 * contains at least the year and copyright holder of the song.
	 */
	private String copyright;
	
	/**
	 * CCLI number, providing integration with CCLI.
	 * 
	 * CCLI stands for Christian Copyright Licensing International. 
	 * CCLI is an organization that offers copyright licensing of 
	 * songs and other resource materials to churches and 
	 * Christian organizations for use in Christian worship.
	 * For registered churches, CCLI offers songs and other 
	 * resources for download. A CCLI ID is assigned to every song. 
	 */
	private int ccliNumber;
	
	/**
	 * The release date tracks the date when a song was released or published.
	 */
	private String releaseDate;
	
	/**
	 * The transposition variable is used when it is necessary to 
	 * move the key or the pitch of chords up or down. 
	 * 
	 * The value must be a positive or negative integer. A negative value 
	 * moves the pitch down by a fixed number of semitones:
	 */
	private int transposition = 0;
	
	/**
	 * The tempo of a song defines the speed at which a song is to be played. 
	 * 
	 * It could be expressed in beats per minute (BPM) or as any text value. 
	 * If the tempo is measured in BPM, it must be a positive integer in the 
	 * range of 30-250. If the tempo is expressed as a phrase, it can 
	 * contain any arbitrary text. 
	 * For example Very Fast, Fast, Moderate, Slow, Very Slow, etc.:
	 */
	private String tempo;
	
	/**
	 * The key determines the musical scale of a song. 
	 * 
	 * For example, A, B, C#, D, Eb, F# or Ab.
	 */
	private String key;
	
	/**
	 * The variant is used to differentiate between songs which are identical, 
	 * but may be performed or sung differently.
	 */
	private String variant;
	
	/**
	 * Contains the name of the publisher of the song
	 */
	private String publisher;
	
	/**
	 * Identifies the version of the song.
	 * 
	 * No song is ever created once, never to be edited again. 
	 * Songs are updated over time, sometimes to add additional verses, 
	 * sometimes to fix spelling or grammatical errors. This value could 
	 * be updated whenever a song changes significantly. It can contain 
	 * any arbitrary text which could help the user to distinguish 
	 * between various versions of a song. 
	 */
	private String version;
	
	/**
	 * Keywords are used for more precise results when searching 
	 * for a song in a song database.
	 */
	private ArrayList<String> keywords = new ArrayList<String>();
	
	/**
	 * The verse order of a song defines the order in which the verses 
	 * are typically sung or performed. 
	 */
	private ArrayList<String> verseOrder = new ArrayList<String>();
	
	/**
	 * Most songs come from some sort of collection of songs, 
	 * be it a book or a folder of some sort. 
	 * 
	 * It may be useful to track where the song comes from. Because songs are 
	 * often found in more than one song book, multiple songbooks can be defined.
	 */
	private ArrayList<SongBook> songBooks = new ArrayList<SongBook>();

	/**
	 * Themes are used to categorize songs. 
	 * 
	 * Having songs categorized can be useful when choosing songs 
	 * for a ceremony or for a particular sermon topic. A song can 
	 * have multiple themes, 
	 */
	private ArrayList<SongTheme> songThemes = new ArrayList<SongTheme>();
	
	/**
	 * The comments variable is used to store any additional, unspecified 
	 * user data in a free-form text field. 
	 * 
	 * A song can contain multiple comments.
	 */
	private ArrayList<String> comments = new ArrayList<String>();

	/**
	 * The lyrics contain one or more verses. 
	 * 
	 * Each item defines a verse or stanza of a song, and contains a 
	 * single mandatory attribute, the name. 
	 */
	private ArrayList<SongVerse> lyrics = new ArrayList<SongVerse>();
	
	/**
	 * Constructor
	 */
	public Song() {
		
	}

	public ArrayList<SongAuthor> getAuthors() {
		return authors;
	}

	public void setAuthors(ArrayList<SongAuthor> authors) {
		this.authors = authors;
	}

	public int getCcliNumber() {
		return ccliNumber;
	}

	public void setCcliNumber(int ccliNumber) {
		this.ccliNumber = ccliNumber;
	}

	public ArrayList<String> getComments() {
		return comments;
	}

	public void setComments(ArrayList<String> comments) {
		this.comments = comments;
	}

	public String getCopyright() {
		return copyright;
	}

	public void setCopyright(String copyright) {
		this.copyright = copyright;
	}

	public String getKey() {
		return key;
	}

	public void setKey(String key) {
		this.key = key;
	}

	public ArrayList<String> getKeywords() {
		return keywords;
	}

	public void setKeywords(ArrayList<String> keywords) {
		this.keywords = keywords;
	}

	public ArrayList<SongVerse> getLyrics() {
		return lyrics;
	}

	public void setLyrics(ArrayList<SongVerse> lyrics) {
		this.lyrics = lyrics;
	}

	public String getPublisher() {
		return publisher;
	}

	public void setPublisher(String publisher) {
		this.publisher = publisher;
	}

	public String getReleaseDate() {
		return releaseDate;
	}

	public void setReleaseDate(String releaseDate) {
		this.releaseDate = releaseDate;
	}

	public ArrayList<SongBook> getSongBooks() {
		return songBooks;
	}

	public void setSongBooks(ArrayList<SongBook> songBooks) {
		this.songBooks = songBooks;
	}

	public ArrayList<SongTheme> getSongThemes() {
		return songThemes;
	}

	public void setSongThemes(ArrayList<SongTheme> songThemes) {
		this.songThemes = songThemes;
	}

	public String getTempo() {
		return tempo;
	}

	public void setTempo(String tempo) {
		this.tempo = tempo;
	}

	public ArrayList<SongTitle> getTitles() {
		return titles;
	}

	public void setTitles(ArrayList<SongTitle> titles) {
		this.titles = titles;
	}

	public int getTransposition() {
		return transposition;
	}

	public void setTransposition(int transposition) {
		this.transposition = transposition;
	}

	public UUID getUuid() {
		return uuid;
	}

	public void setUuid(UUID uuid) {
		this.uuid = uuid;
	}

	public String getVariant() {
		return variant;
	}

	public void setVariant(String variant) {
		this.variant = variant;
	}

	public ArrayList<String> getVerseOrder() {
		return verseOrder;
	}

	public void setVerseOrder(ArrayList<String> verseOrder) {
		this.verseOrder = verseOrder;
	}

	public String getVersion() {
		return version;
	}

	public void setVersion(String version) {
		this.version = version;
	}
	
	/**
	 * Returns the song title as string based on possible 
	 * originality and language attributes
	 * @return 
	 */
	public String getTitle() {
		String title = null;
		for (SongTitle t : getTitles()) {
			if (t.isOriginal()) {
				title = t.getTitle();
			}
		}
		if (title == null && getTitles().size() > 0) {
			title = getTitles().get(0).getTitle();
		}
		return title;
	}
	
	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("Title:").append(getTitle()).append("\n");
		sb.append("Titles:").append(getTitles()).append("\n");
		sb.append("Authors:").append(getAuthors()).append("\n");
		sb.append("Copyright:").append(getCopyright()).append("\n");
		sb.append("CCLI:").append(getCcliNumber()).append("\n");
		sb.append("ReleaseDate:").append(getReleaseDate()).append("\n");
		sb.append("Transposition:").append(getTransposition()).append("\n");
		return sb.toString();
	}
}